package com.faxsun.web.controller.product;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import mblog.core.pojos.Tag;
import mblog.web.controller.BaseController;
import mtons.modules.pojos.Page;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mobile.device.Device;
import org.springframework.mobile.device.DeviceUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.faxsun.core.pojos.enums.TagType;
import com.faxsun.core.service.AggregationService;
import com.faxsun.core.service.FollowListService;
import com.faxsun.core.service.IndexService;
import com.faxsun.core.service.TagService;
import com.faxsun.pojos.TagAggregation;
import com.faxsun.web.controller.FrontViewConstants;
import com.faxsun.web.utils.MetaUtils;
import com.faxsun.web.utils.MobileDetect;
import com.faxsun.web.utils.VisiblePage;

@Controller
@RequestMapping("/product")
public class ProductController extends BaseController {

	private static final Logger LOG = LoggerFactory
			.getLogger(ProductController.class);

	private static final int NEWS_PAGINATION_SIZE = 18;

	@SuppressWarnings("unused")
	private static final int NEWS_RECENT_FETCHSIZE = 1000;

	private static final int NEWS_PAGINATION_DFLT_VISIBLE_SIZE = 5;

	@Autowired
	protected AggregationService productAggregation;

	@Autowired
	protected TagService tagService;

	@Autowired
	protected IndexService indexService;

	@Autowired
	protected FollowListService flService;

	@RequestMapping(value = "/view/{productTagId}", method = RequestMethod.GET)
	public String viewProduct(@PathVariable Long productTagId, ModelMap model,
			HttpServletRequest request) {

		Tag productTag = tagService.getById(productTagId);

		if (productTag != null && productTag.getType().equals(TagType.PRODUCT)) {
			Page page = new Page(1, 0);
			TagAggregation product = productAggregation.aggregateProduct(page,
					productTag);
			Page recommendPage = new Page(1, 4);
			indexService.retrieveRecommendProducts(recommendPage);

			// FIXME:封装页面所需要的元素模型
			model.addAttribute("productTag", productTag);
			model.addAttribute("evluations", product.getEvaluations());
			model.addAttribute("infos", product.getInfos());
			model.addAttribute("recommendProducts", recommendPage.getResults());
			model.addAttribute(FrontViewConstants.VIEW_META_TITLE,
					MetaUtils.formatMetaTitle(productTag.getName()));
			// FIXME:重写关键字生成方式
			model.addAttribute(FrontViewConstants.VIEW_META_KEYWORD,
					productTag.getName());

			// add product info for follow function
			/*
			 * long proId = productTag.getProduct().getId(); long proId =
			 * productTag.getId(); model.addAttribute("proId", proId);
			 * 
			 * int followed_count = flService.countAllMyFollowers(proId, 1);
			 * model.addAttribute("followed_count", followed_count);
			 * 
			 * FollowListPO fl = flService.findFollow(proId, 1L, 1); String
			 * pro_followed = fl == null? "false" : (fl.getStatus() == 0? "true"
			 * : "false"); model.addAttribute("pro_followed", pro_followed);
			 */

		} else {
			LOG.error("Product tag doesn't exist");
			// TODO:跳转到错误页面
		}

		String viewUrl = MobileDetect.getProperView(request,
				"/views/mobile/productDetail",
				FrontViewConstants.VIEW_PRODUCT_AGGR);
		return viewUrl;
	}

	@RequestMapping(value = "/list", method = RequestMethod.GET)
	public String list(
			@RequestParam(value = "pagNo", required = false) Integer pageNo,
			@RequestParam(value = "max", required = false) Integer maxResults,
			ModelMap model, HttpServletRequest request) {

		// FIXME:常量18放入到数据库中
		Page page = wrapPage(pageNo == null ? 1 : pageNo);
		page.setMaxResults(maxResults == null ? 18 : maxResults);
		tagService.listTags(TagType.PRODUCT, page);
		Device device = DeviceUtils.getCurrentDevice(request);
		converToViewList(page, device);
		model.addAttribute("page", page);
		model.addAttribute("tagNav", tagService.listNavTags(2));
		pagination(pageNo == null ? 1 : pageNo, page.getTotalCount(), model,
				request, null);
		model.addAttribute("navigation", "product");

		String viewUrl = MobileDetect.getProperView(request,
				"/views/mobile/productList",
				FrontViewConstants.VIEW_PRODUCT_CATEGORY);
		return viewUrl;

	}

	@RequestMapping(value = "/listPart")
	public String listPart(
			@RequestParam(value = "pagNo", required = false) Integer pageNo,
			@RequestParam(value = "max", required = false) Integer maxResults,
			ModelMap model, HttpServletRequest request) {

		// FIXME:常量18放入到数据库中
		pageNo = Integer.parseInt(request.getParameter("page"));
		Page page = wrapPage(pageNo == null ? 1 : pageNo);
		page.setMaxResults(maxResults == null ? 18 : maxResults);

		// tagService.listTags(TagType.PRODUCT, page);
		String[] tagIds = request.getParameterValues("tagIds");
		List<Tag> tags = new ArrayList<Tag>();
		if (tagIds != null) {
			for (String tagIdStr : tagIds) {
				try {
					long tagId = Long.parseLong(tagIdStr);
					Tag tag = new Tag();
					tag.setId(tagId);
					tags.add(tag);
				} catch (NumberFormatException nfe) {
					continue;
				}

			}
		}
		if (tags.size() > 0)
			productAggregation.aggregateProductByCategoryTag(page, tags);
		else
			tagService.listTags(TagType.PRODUCT, page);
		Device device = DeviceUtils.getCurrentDevice(request);

		converToViewList(page, device);

		model.addAttribute("page", page);
		model.addAttribute("tagNav", tagService.listNavTags(2));

		if (tagIds != null && tagIds.length > 0) {
			pagination(pageNo == null ? 1 : pageNo, page.getTotalCount(),
					model, request, Arrays.asList(tagIds));
		} else {
			pagination(pageNo == null ? 1 : pageNo, page.getTotalCount(),
					model, request, null);
		}

		String viewUrl = MobileDetect.getProperView(request,
				"/views/mobile/productList",
				"/views/product/partials/proHorizontalList");
		return viewUrl;

	}

	@RequestMapping(value = "/list/filter", method = RequestMethod.GET)
	public String listByTag(@RequestParam(value = "tagIds") String tagIds,
			@RequestParam(value = "pagNo", required = false) Integer pageNo,
			@RequestParam(value = "max", required = false) Integer maxResults,
			ModelMap model, HttpServletRequest request) {
		Page page = wrapPage(pageNo == null ? 1 : pageNo);
		page.setMaxResults(maxResults == null ? 18 : maxResults);
		page.setCount(true);

		// tagService.listTags(TagType.PRODUCT, page);
		List<Tag> tags = new ArrayList<Tag>();
		String[] tagIdArray = tagIds.split(",");
		for (String tagIdStr : tagIdArray) {
			try {
				long tagId = Long.parseLong(tagIdStr);
				Tag tag = new Tag();
				tag.setId(tagId);
				tags.add(tag);
			} catch (NumberFormatException nfe) {
				continue;
			}

		}
		productAggregation.aggregateProductByCategoryTag(page, tags);

		Device device = DeviceUtils.getCurrentDevice(request);
		converToViewList(page, device);
		model.addAttribute("page", page);

		List<String> tagIdStrArray = new ArrayList<String>(
				Arrays.asList(tagIdArray));
		List<Tag> navTags = tagService.listNavTags(2);
		for (Tag tag : navTags) {
			if (tagIdStrArray.contains(String.valueOf(tag.getId()))) {
				tag.setCurTag(true);
			} else {
				tag.setCurTag(false);
			}
		}
		model.addAttribute("tagNav", navTags);

		pagination(pageNo == null ? 1 : pageNo, page.getTotalCount(), model,
				request, Arrays.asList(tagIdArray));
		model.addAttribute("navigation", "product");

		String viewUrl = MobileDetect.getProperView(request,
				"/views/mobile/productList",
				FrontViewConstants.VIEW_PRODUCT_CATEGORY);
		return viewUrl;

	}

	private void converToViewList(Page page, Device device) {
		// 把list转换为list<list>,且每个子list中仅有3个元素
		@SuppressWarnings("unchecked")
		List<Tag> tags = (List<Tag>) page.getResults();
		List<List<Tag>> tagsLists = new ArrayList<List<Tag>>();

		if (device.isMobile() || device.isTablet()) {
			page.setResults(tags);
		} else {
			List<Tag> subTagList = new ArrayList<Tag>();
			for (int i = 0; i < tags.size(); i++) {

				// FIXME:将3放到setting，存入数据库中，可以从管理端直接设置
				if (i > 0 && i % 3 == 0) {
					tagsLists.add(subTagList);
					subTagList = new ArrayList<Tag>();
				}
				subTagList.add(tags.get(i));
			}
			tagsLists.add(subTagList);
			page.setResults(tagsLists);
		}

	}

	private void pagination(int pageNo, int totalNewsSize, ModelMap model,
			HttpServletRequest request, List<String> tags) {

		int curPageId = pageNo;

		// add max page
		int maxPageId = (totalNewsSize / NEWS_PAGINATION_SIZE)
				+ (totalNewsSize % NEWS_PAGINATION_SIZE == 0 ? 0 : 1);
		if (curPageId > maxPageId) {
			curPageId = maxPageId;
		}
		model.addAttribute("maxPage", maxPageId);
		model.addAttribute("curPage", curPageId);
		model.addAttribute("prevPage", curPageId - 1 < 1 ? 1 : curPageId - 1);
		model.addAttribute("nextPage", curPageId + 1 > maxPageId ? maxPageId
				: curPageId + 1);

		// add paging post url
		String contextPath = request.getContextPath();
		String url = null;
		if (tags != null && tags.size() > 0) {
			url = contextPath + "/product/listPart?";
			for (int i = 0; i < tags.size(); i++) {
				if (i > 0) {
					url += "&";
				}
				url += "tagIds=" + tags.get(i);
			}
		} else {
			url = contextPath + "/product/listPart";
		}
		model.addAttribute("url", url);

		// add visible page for pagination
		List<VisiblePage> visiblePages = new ArrayList<VisiblePage>(
				NEWS_PAGINATION_DFLT_VISIBLE_SIZE);
		int startPageId = curPageId - 2 < 1 ? 1 : curPageId - 2;
		int endPageId = curPageId + 2 > maxPageId ? maxPageId : curPageId + 2;
		for (int i = startPageId; i <= endPageId; i++) {
			VisiblePage vp = new VisiblePage();
			vp.setId(i);
			if (i == curPageId) {
				vp.setCurPage(true);
			}
			visiblePages.add(vp);
		}
		model.addAttribute("visiblePages", visiblePages);
	}

	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/json", method = RequestMethod.POST)
	@ResponseBody
	public List<Tag> listByTagPost(
			@RequestParam(value = "tagIds") String tagIds,
			@RequestParam(value = "pagNo", required = false) Integer pageNo,
			@RequestParam(value = "max", required = false) Integer maxResults,
			ModelMap model, HttpServletRequest request,
			HttpServletResponse response) {
		Page page = wrapPage(pageNo == null ? 1 : pageNo);
		page.setMaxResults(maxResults == null ? 18 : maxResults);
		page.setCount(true);

		// tagService.listTags(TagType.PRODUCT, page);
		List<Tag> tags = new ArrayList<Tag>();
		String[] tagIdArray = tagIds.split(",");
		for (String tagIdStr : tagIdArray) {
			try {
				long tagId = Long.parseLong(tagIdStr);
				Tag tag = new Tag();
				tag.setId(tagId);
				tags.add(tag);
			} catch (NumberFormatException nfe) {
				continue;
			}

		}
		productAggregation.aggregateProductByCategoryTag(page, tags);

		List<Tag> tagsJson = (List<Tag>) page.getResults();
		int maxPageId = (page.getTotalCount() / NEWS_PAGINATION_SIZE) + 1;
		if (pageNo > maxPageId) {
			return Collections.emptyList();
		} else {
			return tagsJson;
		}

	}
}
